package com.jdy.haoduoai.view;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.PointF;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.animation.RotateAnimation;
import android.widget.RelativeLayout;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class SpinCircleView extends RelativeLayout {

  private final static String TAG = "SpinCircleView";

  private int CIRCLE_RADIUS = 50;

  private final int DOT_RADIUS = 10;

  private final int DOT_COLOR = Color.RED;

  private PointF mCenter;

  private int WIDTH;

  private int HEIGHT;

  private final static int SAMPLE_COUNT = 20;

  private List<PointF> mCirclePoints;

  private Paint mPaint;

  private Matrix mMatrix;

  private final static double DEGREE_INRADIANS = -Math.PI / 30;

  private final Runnable runnable = new Runnable() {
    @Override
    public void run() {
      rotateByAngle();
      invalidate();
      canvasHandler.postDelayed(runnable, intervalMills);
    }
  };

  private final Handler canvasHandler;

  private final int intervalMills = 1000;

  private OnSpinCompleteListener onSpinCompletionListener;

  private RotateAnimation rotateAnimation;

  public SpinCircleView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    // TODO Auto-generated constructor stub
    init(context, attrs);

    canvasHandler = new Handler();
  }

  public SpinCircleView(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
    // TODO Auto-generated constructor stub
  }

  public SpinCircleView(Context context) {
    this(context, null);
    // TODO Auto-generated constructor stub
  }

  private void init(Context context, AttributeSet attrs) {
    

  }

  /**
   * Get point from the circle by a certain angle.
   */
  private PointF getPointByAngle(PointF Center, float radius, double rotateAngle) {
    PointF p = new PointF();
    p.x = Center.x + radius * (float) Math.cos(rotateAngle);
    p.y = Center.y + radius * (float) Math.sin(rotateAngle);
    return p;
  }

  /**
   * Get an array of points by a given range of angle.
   * 
   * @param start
   * @param end
   * @param samples
   * @return
   */
  private PointF[] getPointsByAngleRange(PointF Center, float radius,
      double start, double end, int samples) {
    double range = Math.abs(end - start);
    boolean reverse = false;
    if (end < start) {
      reverse = true;
      double tmp = start;
      start = end;
      end = tmp;
    }
    double step = range / samples;
    List<PointF> points = new ArrayList<PointF>();
    double c = start;
    for (; c <= end; c += step) {
      PointF n = getPointByAngle(Center, radius, c);
      points.add(n);
    }
    if (reverse)
      Collections.reverse(points);
    return points.toArray(new PointF[points.size()]);
  }

  private void rotateByAngle() {
    for (PointF point : mCirclePoints) {
      float[] pts = new float[2];
      pts[0] = point.x;
      pts[1] = point.y;
      mMatrix.mapPoints(pts);
      point.x = pts[0];
      point.y = pts[1];
    }
  }

  @Override
  public void draw(Canvas canvas) {
    super.draw(canvas);
    for (PointF point : mCirclePoints) {
      canvas.drawCircle(point.x, point.y, DOT_RADIUS, mPaint);
    }
  }

  // @Override
  // protected void onDraw(Canvas canvas) {
  // super.onDraw(canvas);
  //
  // }

  @Override
  protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    WIDTH = w;
    HEIGHT = h;
    mCenter = new PointF();
    mCenter.x = WIDTH / 2;
    mCenter.y = HEIGHT / 2;
    int smaller = Math.min(WIDTH, HEIGHT);
    CIRCLE_RADIUS = smaller / 2 - DOT_RADIUS;
    PointF[] circlePoints = getPointsByAngleRange(mCenter, CIRCLE_RADIUS, 0,
        Math.PI * 2, SAMPLE_COUNT);
    mCirclePoints = Arrays.asList(circlePoints);
    mPaint = new Paint();
    mPaint.setColor(DOT_COLOR);
    mPaint.setStyle(Style.FILL);
    mPaint.setAntiAlias(true);
    mPaint.setStrokeWidth(1.0f);
    mMatrix = new Matrix();
    mMatrix.setRotate((float) DEGREE_INRADIANS, mCenter.x, mCenter.y);
    // rotateAnimation = new RotateAnimation(0, (float) (Math.PI * 2),
    // mCenter.x,
    // mCenter.y);
    // rotateAnimation.setDuration(intervalMills);
    // rotateAnimation.setRepeatMode(Animation.INFINITE);
    // rotateAnimation.setRepeatCount(Animation.INFINITE);
    // this.startAnimation(rotateAnimation);
    canvasHandler.postDelayed(runnable, intervalMills);
  }

  @Override
  public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int desiredWidth = 600;
    int desiredHeight = 600;

    int widthMode = MeasureSpec.getMode(widthMeasureSpec);
    int widthSize = MeasureSpec.getSize(widthMeasureSpec);
    int heightMode = MeasureSpec.getMode(heightMeasureSpec);
    int heightSize = MeasureSpec.getSize(heightMeasureSpec);

    int width;
    int height;

    // Measure Width
    if (widthMode == MeasureSpec.EXACTLY) {
      // Must be this size
      width = widthSize;
    } else if (widthMode == MeasureSpec.AT_MOST) {
      // Can't be bigger than...
      width = Math.min(desiredWidth, widthSize);
    } else {
      // Be whatever you want
      width = desiredWidth;
    }

    // Measure Height
    if (heightMode == MeasureSpec.EXACTLY) {
      // Must be this size
      height = heightSize;
    } else if (heightMode == MeasureSpec.AT_MOST) {
      // Can't be bigger than...
      height = Math.min(desiredHeight, heightSize);
    } else {
      // Be whatever you want
      height = desiredHeight;
    }

    // MUST CALL THIS
    setMeasuredDimension(width, height);
  }

  public interface OnSpinCompleteListener {
    void onComplete(SpinCircleView spinCircleView);
  }

}
